import cv2
import numpy as np
import matplotlib.pyplot as plt


def auto_dense_stripe_roi(img,
                          win_size=32,
                          stride=16,
                          thres_percentile=95,
                          margin=5):
    """
    自动检测图像中最密集条纹区域，返回 ROI 框 (x, y, w, h)。
    img : 8-bit 灰度图
    若未检测到，打印提示并返回 None
    """
    h, w = img.shape[:2]

    # 1) 计算梯度能量图
    gx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
    gy = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
    grad_mag = np.sqrt(gx**2 + gy**2)

    # 2) 滑动窗口统计每个块的能量均值与方差
    idx_y, idx_x = np.mgrid[0:h-win_size:stride, 0:w-win_size:stride]
    idx_y = idx_y.ravel()
    idx_x = idx_x.ravel()
    score = np.empty(len(idx_x))

    for k, (y0, x0) in enumerate(zip(idx_y, idx_x)):
        patch = grad_mag[y0:y0+win_size, x0:x0+win_size]
        score[k] = np.mean(patch) * np.std(patch)   # 均值×方差，突出条纹

    # 3) 自适应阈值
    th = np.percentile(score, thres_percentile)
    mask = score >= th
    if not np.any(mask):
        print("未检测到明显的条纹密集区域")
        return None

    # 4) 由满足阈值的窗口中心点求最小外接矩形
    centers = np.column_stack((idx_x[mask] + win_size//2,
                               idx_y[mask] + win_size//2))
    x_min, y_min = centers.min(axis=0)
    x_max, y_max = centers.max(axis=0)

    # 5) 加边距并限制在图像边界内
    x = max(0, int(x_min - margin))
    y = max(0, int(y_min - margin))
    roi_w = min(w - x, int(x_max - x_min + 2*margin))
    roi_h = min(h - y, int(y_max - y_min + 2*margin))

    roi = (x, y, roi_w, roi_h)

    # 6) 可视化
    vis = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    cv2.rectangle(vis, (x, y), (x + roi_w, y + roi_h), (0, 0, 255), 2)
    plt.figure(figsize=(5, 5))
    plt.title('Auto-detected dense stripe ROI')
    plt.imshow(vis[..., ::-1])
    plt.axis('off')
    plt.show()

    return roi


# ---------------- demo ----------------
if __name__ == '__main__':
    img = cv2.imread('../img/new/0012.tif', 0)
    if img is None:
        raise FileNotFoundError('../img/pic1.jpg')

    roi = auto_dense_stripe_roi(img)
    if roi is None:
        exit()
    print('自动 ROI:', roi)
    # 接下来把 roi 传给 brightest_symmetric_spot 即可
    # pair, rec = brightest_symmetric_spot('../img/pic1.jpg', roi=roi)